 
#include <stdbool.h>
#include "stm32f1xx_hal.h"
#include <stdio.h>

//PID and VID of the Sony PS3 devices
#define PS3_VID                 0x054C  // Sony Corporation
#define PS3_PID                 0x0268  // PS3 Controller DualShock 3
#define PS3NAVIGATION_PID       0x042F  // Navigation controller
#define PS3MOVE_PID             0x03D5  // Motion controller

#define IOGEAR_GBU521_VID       0x0A5C // The IOGEAR GBU521 dongle does not presents itself correctly, so we have to check for it manually
#define IOGEAR_GBU521_PID       0x21E8

/* Bluetooth dongle data taken from descriptors */
#define BULK_MAXPKTSIZE         64 // Max size for ACL data

// Used in control endpoint header for HCI Commands
#define bmREQ_HCI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE

/* Bluetooth HCI states for hci_task() */

#define HCI_INIT_STATE                  0x00
#define HCI_RESET_STATE                 0x01
#define HCI_CLASS_STATE                 0x02
#define HCI_BDADDR_STATE                0x03
#define HCI_LOCAL_VERSION_STATE         0x04
#define HCI_SET_NAME_STATE              0x05
#define HCI_WRITE_EN_STATE              0x06
#define HCI_CHECK_DEVICE_SERVICE        0x07

#define HCI_INQUIRY_STATE               0x08 // These three states are only used if it should pair and connect to a device
#define HCI_CONNECT_DEVICE_STATE        0x09
#define HCI_CONNECTED_DEVICE_STATE      0x0a

#define HCI_SCANNING_STATE              0x0b
#define HCI_CONNECT_IN_STATE            0x0c
#define HCI_REMOTE_NAME_STATE           0x0d
#define HCI_CONNECTED_STATE             0x0e
#define HCI_DISABLE_SCAN_STATE          0x0f
#define HCI_DONE_STATE                  0x10
#define HCI_DISCONNECT_STATE            0x11
#define HCI_CHANGE_PACKET_TYPE			0x12
#define HCI_READ_VERSION				0x13	
#define HCI_READ_REMOTE_NAME			0x14
#define HCI_WRITE_LINK_POLICY			0x15
#define HCI_WRITE_AUTHENTICATION_STATE	0x16
#define HCI_PSCAN_REP_STATE				0x17

/* HCI event flags*/
#define HCI_FLAG_CMD_COMPLETE           (1UL << 0)
#define HCI_FLAG_CONNECT_COMPLETE       (1UL << 1)
#define HCI_FLAG_DISCONNECT_COMPLETE    (1UL << 2)
#define HCI_FLAG_REMOTE_NAME_COMPLETE   (1UL << 3)
#define HCI_FLAG_INCOMING_REQUEST       (1UL << 4)
#define HCI_FLAG_READ_BDADDR            (1UL << 5)
#define HCI_FLAG_READ_VERSION           (1UL << 6)
#define HCI_FLAG_DEVICE_FOUND           (1UL << 7)
#define HCI_FLAG_CONNECT_EVENT          (1UL << 8)
#define HCI_FLAG_CHANGE_PTYPE_COMPLETE  (1UL << 9)
#define HCI_FLAG_REMOTE_VER_COMPLETE	(1UL << 10)
#define HCI_FLAG_PSCAN_REP				(1UL << 11)



/* HCI Events managed */
#define EV_INQUIRY_COMPLETE                             0x01
#define EV_INQUIRY_RESULT                               0x02
#define EV_CONNECT_COMPLETE                             0x03
#define EV_INCOMING_CONNECT                             0x04
#define EV_DISCONNECT_COMPLETE                          0x05
#define EV_AUTHENTICATION_COMPLETE                      0x06
#define EV_REMOTE_NAME_COMPLETE                         0x07
#define EV_ENCRYPTION_CHANGE                            0x08
#define EV_CHANGE_CONNECTION_LINK                       0x09
#define EV_ROLE_CHANGED                                 0x12
#define EV_NUM_COMPLETE_PKT                             0x13
#define EV_PIN_CODE_REQUEST                             0x16
#define EV_LINK_KEY_REQUEST                             0x17
#define EV_LINK_KEY_NOTIFICATION                        0x18
#define EV_DATA_BUFFER_OVERFLOW                         0x1A
#define EV_MAX_SLOTS_CHANGE                             0x1B
#define EV_CHANGE_PACKET_TYPE_COMPLETE					0x1D
#define EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE     0x0C
#define EV_QOS_SETUP_COMPLETE                           0x0D
#define EV_COMMAND_COMPLETE                             0x0E
#define EV_COMMAND_STATUS                               0x0F
#define EV_LOOPBACK_COMMAND                             0x19
#define EV_PAGE_SCAN_REP_MODE                           0x20
#define EV_IO_Capability_Request                        0x31
#define EV_User_Confirmation_Request                    0x33
#define EV_HCI_Inquiry_Result_With_RSSI                 0x22
#define EV_Simple_Pairing_Complete                 0x36

/* Bluetooth states for the different Bluetooth drivers */
#define L2CAP_WAIT                      0
#define L2CAP_DONE                      1

/* Used for HID Control channel */
#define L2CAP_CONTROL_CONNECT_REQUEST   2
#define L2CAP_CONTROL_CONFIG_REQUEST    3
#define L2CAP_CONTROL_SUCCESS           4
#define L2CAP_CONTROL_DISCONNECT        5

/* Used for HID Interrupt channel */
#define L2CAP_INTERRUPT_SETUP           6
#define L2CAP_INTERRUPT_CONNECT_REQUEST 7
#define L2CAP_INTERRUPT_CONFIG_REQUEST  8
#define L2CAP_INTERRUPT_DISCONNECT      9

/* Used for SDP channel */
#define L2CAP_SDP_WAIT                  10
#define L2CAP_SDP_SUCCESS               11

/* Used for RFCOMM channel */
#define L2CAP_RFCOMM_WAIT               12
#define L2CAP_RFCOMM_SUCCESS            13

#define L2CAP_DISCONNECT_RESPONSE       14 // Used for both SDP and RFCOMM channel

/* Bluetooth states used by some drivers */
#define TURN_ON_LED                     17
#define PS3_ENABLE_SIXAXIS              18
#define WII_CHECK_MOTION_PLUS_STATE     19
#define WII_CHECK_EXTENSION_STATE       20
#define WII_INIT_MOTION_PLUS_STATE      21

/* L2CAP event flags for HID Control channel */
#define L2CAP_FLAG_CONNECTION_CONTROL_REQUEST           (1UL << 0)
#define L2CAP_FLAG_CONFIG_CONTROL_SUCCESS               (1UL << 1)
#define L2CAP_FLAG_CONTROL_CONNECTED                    (1UL << 2)
#define L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE          (1UL << 3)

/* L2CAP event flags for HID Interrupt channel */
#define L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST         (1UL << 4)
#define L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS             (1UL << 5)
#define L2CAP_FLAG_INTERRUPT_CONNECTED                  (1UL << 6)
#define L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE        (1UL << 7)

/* L2CAP event flags for SDP channel */
#define L2CAP_FLAG_CONNECTION_SDP_REQUEST               (1UL << 8)
#define L2CAP_FLAG_CONFIG_SDP_SUCCESS                   (1UL << 9)
#define L2CAP_FLAG_DISCONNECT_SDP_REQUEST               (1UL << 10)

/* L2CAP event flags for RFCOMM channel */
#define L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST            (1UL << 11)
#define L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS                (1UL << 12)
#define L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST            (1UL << 13)

#define L2CAP_FLAG_DISCONNECT_RESPONSE                  (1UL << 14)

/* Macros for L2CAP event flag tests */
#define l2cap_check_flag(flag) (l2cap_event_flag & (flag))
#define l2cap_set_flag(flag) (l2cap_event_flag |= (flag))
#define l2cap_clear_flag(flag) (l2cap_event_flag &= ~(flag))

/* L2CAP signaling commands */
#define L2CAP_CMD_COMMAND_REJECT        0x01
#define L2CAP_CMD_CONNECTION_REQUEST    0x02
#define L2CAP_CMD_CONNECTION_RESPONSE   0x03
#define L2CAP_CMD_CONFIG_REQUEST        0x04
#define L2CAP_CMD_CONFIG_RESPONSE       0x05
#define L2CAP_CMD_DISCONNECT_REQUEST    0x06
#define L2CAP_CMD_DISCONNECT_RESPONSE   0x07
#define L2CAP_CMD_ECHO_REQUEST    0x08
#define L2CAP_CMD_ECHO_RESPONSE   0x09
#define L2CAP_CMD_INFORMATION_REQUEST   0x0A
#define L2CAP_CMD_INFORMATION_RESPONSE  0x0B

// Used For Connection Response - Remember to Include High Byte
#define PENDING     0x01
#define SUCCESSFUL  0x00

/* Bluetooth L2CAP PSM - see http://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm */
#define SDP_PSM         0x01 // Service Discovery Protocol PSM Value
#define RFCOMM_PSM      0x03 // RFCOMM PSM Value
#define HID_CTRL_PSM    0x11 // HID_Control PSM Value
#define HID_INTR_PSM    0x13 // HID_Interrupt PSM Value

// Used to determine if it is a Bluetooth dongle
#define WI_SUBCLASS_RF      0x01 // RF Controller
#define WI_PROTOCOL_BT      0x01 // Bluetooth Programming Interface

#define BTD_MAX_ENDPOINTS   4
#define BTD_NUM_SERVICES    1 // Max number of Bluetooth services - if you need more than 4 simply increase this number

#define PAIR    1

#define usart2_log 1

enum HCICommand 
{
    HCI_Null = 0x0000,
    /// <summary>
    ///     Command to accept a new connection request.
    /// </summary>
    HCI_Accept_Connection_Request = 0x0409,
    /// <summary>
    ///     Command to reject a new connection request.
    /// </summary>
    HCI_Reject_Connection_Request = 0x040A,
    /// <summary>
    ///     Command to determine the user friendly name of the connected device.
    /// </summary>
    HCI_Remote_Name_Request = 0x0419,
    /// <summary>
    ///     Command to reset the host controller, link manager and the radio module.
    /// </summary>
    HCI_Reset = 0x0C03,
    /// <summary>
    ///     Command to set the status of the Scan_Enable configuration.
    /// </summary>
    HCI_Write_Scan_Enable = 0x0C1A,
    HCI_Read_Buffer_Size = 0x1005,
    HCI_Read_BD_ADDR = 0x1009,
    HCI_Read_Local_Version_Info = 0x1001,
    HCI_Create_Connection = 0x0405,
    HCI_Disconnect = 0x0406,
    HCI_Link_Key_Request_Reply = 0x040B,
    HCI_Link_Key_Request_Negative_Reply = 0x040C,
    HCI_PIN_Code_Request_Reply = 0x040D,
    HCI_PIN_Code_Request_Negative_Reply = 0x040E,
    HCI_Inquiry = 0x0401,
    HCI_Inquiry_Cancel = 0x0402,
    HCI_Write_Inquiry_Transmit_Power_Level = 0x0C59,
    HCI_Write_Inquiry_Mode = 0x0C45,
    HCI_Write_Simple_Pairing_Mode = 0x0C56,
    HCI_Write_Simple_Pairing_Debug_Mode = 0x1804,
    HCI_Write_Authentication_Enable = 0x0C20,
    HCI_Write_Page_Timeout = 0x0C18,
    HCI_Write_Page_Scan_Activity = 0x0C1C,
    HCI_Write_Page_Scan_Type = 0x0C47,
    HCI_Write_Inquiry_Scan_Activity = 0x0C1E,
    HCI_Write_Inquiry_Scan_Type = 0x0C43,
    HCI_Write_Class_of_Device = 0x0C24,
    HCI_Write_Extended_Inquiry_Response = 0x0C52,
    HCI_Write_Local_Name = 0x0C13,
    HCI_Set_Event_Mask = 0x0C01,
    HCI_IO_Capability_Request_Reply = 0x042B,
    HCI_User_Confirmation_Request_Reply = 0x042C,
    HCI_Set_Connection_Encryption = 0x0413,
    HCI_Authentication_Requested = 0x0411,
    HCI_Change_Connection_Link_Key = 0x0415,
    HCI_Read_Stored_Link_Key = 0x0C0D,
    HCI_Write_Stored_Link_Key = 0x0C11,
    HCI_Delete_Stored_Link_Key = 0x0C12,
    HCI_Write_Link_Policy_Settings=0x080d,
    HCI_Sniff_Subrating=0x0811,
    Change_Connection_Packet_Type = 0x0f04,
		HCI_Read_Remote_Version =0x041d,
		HCI_Write_Link_Key_Timeout =0x0c37
		
};





//class BluetoothService;
 
 #ifndef min
#define min(a,b)            (((a) < (b)) ? (a) : (b))
#endif

 	//uint8_t min(uint8_t,uint8_t);
	struct RemoteDevice{
		
	uint8_t hci_handle[2];

  uint8_t disc_bdaddr[6];
	
	uint8_t disc_offset[2];
	
  uint8_t disc_linkkey[16];
	char remote_name[30];	
	
	char state;
 		
	};
	
	struct QueueFormat
	{
	  uint8_t data[60];
	  uint16_t length;
		bool NeedSended;
		uint8_t commandtype;
	};
	

void HCI_SendQueue(void);	
	
 void HCI_Command(enum HCICommand hcicommd,uint8_t *data, uint8_t nbytes);
 /** Reset the Bluetooth dongle. */
 void hci_reset(void);
 /** Read the Bluetooth address of the dongle. */
 void hci_read_bdaddr(void);
 /** Read the HCI Version of the Bluetooth dongle. */
 void hci_read_local_version_information(void);
 /**
  * Set the local name of the Bluetooth dongle.
  * @param name Desired name.
  */
 void hci_set_local_name(const char* name);
 /** Enable visibility to other Bluetooth devices. */
 void hci_write_scan_enable(void);
 /** Disable visibility to other Bluetooth devices. */
 void hci_write_scan_disable(void);
 /** Read the remote devices name. */
 void hci_remote_name(struct RemoteDevice* rd);
 /** Accept the connection with the Bluetooth device. */
 void hci_accept_connection(struct RemoteDevice* rd);
 /**
  * Disconnect the HCI connection.
  * @param handle The HCI Handle for the connection.
  */
 void hci_disconnect(struct RemoteDevice* rd);
 /**
  * Respond with the pin for the connection.
  * The pin is automatically set for the Wii library,
  * but can be customized for the SPP library.
  */
 void hci_pin_code_request_reply(struct RemoteDevice* rd);
 /** Respons when no pin was set. */
 void hci_pin_code_negative_request_reply(struct RemoteDevice* rd);
 /**
  * Command is used to reply to a Link Key Request event from the BR/EDR Controller
  * if the Host does not have a stored Link Key for the connection.
  */
 void hci_link_key_request_negative_reply(struct RemoteDevice* rd);
 /** Used to try to authenticate with the remote device. */
 void hci_authentication_request(struct RemoteDevice* rds);
 /** Start a HCI inquiry. */
 void hci_inquiry(void);
 /** Cancel a HCI inquiry. */
 void hci_inquiry_cancel(void);
 /** Connect to last device communicated with. */

 /**
  * Connect to device.
  * @param bdaddr Bluetooth address of the device.
  */
 void hci_connect(struct RemoteDevice* rd);
 /** Used to a set the class of the device. */
 void hci_write_class_of_device(void);
 /**@}*/
	/* Change packet type allowed on the link */
	void hci_change_packet_type(void);
	
	void hci_read_remote_version(void);
	
	void hci_write_link_policy(struct RemoteDevice* rd);
	
	void hci_write_link_timeout(struct RemoteDevice* rd);
	
	void hci_set_AFH(void);
	
	void hci_write_authentication_enable(void);
	
	void hci_write_extended_inquiry_response(void); 
	
	void hci_read_buffer_size(void);
	
	void hci_delete_stored_link_key(struct RemoteDevice* rds);
	
	void hci_link_key_request_reply(struct RemoteDevice* rd);
	
	void hci_io_capability_request_reply(struct RemoteDevice* rd);
	
	void hci_user_confirmation_request_reply(struct RemoteDevice* rd);
	
void  hci_sniff_subrating(struct RemoteDevice* rd);

void hci_write_simple_paring_mode(void);
void hci_write_simple_paring_debug_mode(void);
void hci_set_event_mask(void);

void hci_write_page_timeout(void);

void hci_write_page_scan_activity(void);

void hci_write_page_scan_type(void);

void hci_write_inquiry_scan_activity(void);
void hci_write_inquiry_scan_type(void);
void hci_write_inquiry_mode(void);
void hci_write_class_of_device(void);
void hci_write_extended_inquiry_response(void);
void hci_write_local_name(void);
void hci_reject_connection_request(uint8_t* tmp_bdaddr);


 /** @name L2CAP Commands */
 /**
  * Used to send L2CAP Commands.
  * @param handle      HCI Handle.
  * @param data        Data to send.
  * @param nbytes      Number of bytes to send.
  * @param channelLow,channelHigh  Low and high byte of channel to send to.
	* uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00
  * If argument is omitted then the Standard L2CAP header: Channel ID (0x01) for ACL-U will be used.
  */
 void L2CAP_Command( struct RemoteDevice* rd, uint8_t* data, uint8_t nbytes, uint8_t channelLow, uint8_t channelHigh);
 /**
  * L2CAP Connection Request.
  * @param handle HCI handle.
  * @param rxid   Identifier.
  * @param scid   Source Channel Identifier.
  * @param psm    Protocol/Service Multiplexer - see: https://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm.
  */
 void l2cap_connection_request( struct RemoteDevice* rd, uint8_t rxid, uint8_t* scid, uint16_t psm);
 /**
  * L2CAP Connection Response.
  * @param handle HCI handle.
  * @param rxid   Identifier.
  * @param dcid   Destination Channel Identifier.
  * @param scid   Source Channel Identifier.
  * @param result Result - First send ::PENDING and then ::SUCCESSFUL.
  */
 void l2cap_connection_response(struct RemoteDevice* rd,  uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result);
 /**
  * L2CAP Config Request.
  * @param handle HCI Handle.
  * @param rxid   Identifier.
  * @param dcid   Destination Channel Identifier.
  */
 void l2cap_config_request( struct RemoteDevice* rd, uint8_t rxid, uint8_t* dcid);
 /**
  * L2CAP Config Response.
  * @param handle HCI Handle.
  * @param rxid   Identifier.
  * @param scid   Source Channel Identifier.
  */
 void l2cap_config_response(struct RemoteDevice* rd,  uint8_t rxid, uint8_t* scid);
 /**
  * L2CAP Disconnection Request.
  * @param handle HCI Handle.
  * @param rxid   Identifier.
  * @param dcid   Device Channel Identifier.
  * @param scid   Source Channel Identifier.
  */
 void l2cap_disconnection_request( struct RemoteDevice* rd, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
 /**
  * L2CAP Disconnection Response.
  * @param handle HCI Handle.
  * @param rxid   Identifier.
  * @param dcid   Device Channel Identifier.
  * @param scid   Source Channel Identifier.
  */
 void l2cap_disconnection_response( struct RemoteDevice* rd, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
 /**
  * L2CAP Information Response.
  * @param handle       HCI Handle.
  * @param rxid         Identifier.
  * @param infoTypeLow,infoTypeHigh  Infotype.
  */
 void l2cap_information_response( struct RemoteDevice* rd, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh);
 /**@}*/
 
	
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
